Setting up the environment

# Packages
library(ggplot2)
library(dplyr)
library(plotly)
library(tidyr)
library(RColorBrewer)
library(limma)
library(gplots)
library(edgeR)
library(devtools)
library(ggbiplot)
library(DESeq)
library(geneplotter)
library(Rtsne)
set.seed(1234) # makes everything reproductible 
meta_data <- read.table("../Data/raw_data/meta_data.txt", header = TRUE)
dataInitial <- read.table("../Data/raw_data/expn_matrix.txt", header = TRUE, row.names = 1)
spike_data <- read.table("../Data/raw_data/expn_matrix_spike.txt", header = TRUE, row.names = 1)

Normalization

Kevin’s normalization

Here the data is normalized based on the spike_data we have. Although this seems to be correct, there could be some issues: See post.

spike_data <- rbind(spike_data, "Totals" = colSums(spike_data)) #finding sum of column and adding it as new row
scaled_totals <- spike_data["Totals", ]
average_reads <- rowMeans(scaled_totals)
scaled_totals <- rbind(scaled_totals, "Scale" = scaled_totals[1, ] / average_reads) #dividing total spike values by average spike values
dim_names <- list(row.names(dataInitial))       #setting dim_names for upcoming matrix
dim_names[2] <- list(colnames((dataInitial)))
normalized_data <- matrix(nrow = nrow(dataInitial), ncol = ncol(dataInitial), dimnames = dim_names) #pre-making a matrix
for(i in 1: ncol(dataInitial)){   #for loop which scales data and saves it as normalized_data
  normalized_data[ , i] <- dataInitial[ , i] / scaled_totals[2, i]
}
normalized_data <- as.data.frame(normalized_data)
#normalizing for cell size (cellular miRNA counts)
total_data <- rbind(spike_data, "Total Spike" = colSums(spike_data), "Total Reads" = colSums(dataInitial))
total_cellular <- total_data["Total Reads", ]
average_reads <- rowMeans(total_cellular)
cell_scales <- rbind(total_cellular, "Scale" = total_cellular[1, ] / average_reads) #dividing total spike values by average spike values
dim_names <- list(row.names(dataInitial))       #setting dim_names for upcoming matrix
dim_names[2] <- list(colnames((dataInitial)))
normalized_data2 <- matrix(nrow = nrow(dataInitial), ncol = ncol(dataInitial), dimnames = dim_names) #pre-making a matrix
for(i in 1: ncol(dataInitial)){   #for loop which scales data and saves it as normalized_data
  normalized_data2[ , i] <- normalized_data[ , i] / scaled_totals[2, i]
}
normalized_data2 <- as.data.frame(normalized_data2)
# deleting dead cells
alive_indexes <- list() #initializing lists
k <- 1  #initializing counter
for(i in 1:ncol(total_data)){
  if(total_data["Total Reads", i] > 20000){
    alive_indexes[k] <- i
    k <- k + 1
  }
}
alive_data <- normalized_data2[ , as.numeric(alive_indexes)]
alive_meta_data <- meta_data[as.numeric(alive_indexes), ]
#Saving completely normalized data as n_data and n_meta_data
n_data <- alive_data
n_meta_data <- alive_meta_data
#makes group and design matrix
data_day <- as.character(n_meta_data$Population)
data_day <- recode(data_day, "HL60D0" = "Day 0", "HL60D1" = "Day 1", "HL60D3" = "Day 3", "HL60D7" = "Day 7")
data_day <-factor(data_day)
design <- model.matrix(~0 + n_meta_data$Population)
#deletes "n_meta_data$Population" from name of columns
colnames(design) <- gsub("n_meta_data\\$Population", "", colnames(design))
#lets call intercept HL60D0
#colnames(design)[1] <- "HL60D0"
# Keeps genes without all zeros miRNA
dataNZ <- n_data[which(rowSums(n_data) > 0),] 
#making the contrast matrix
# let's suppose for now that we want to compare each group with each other ?????????????????????????
contrastMatrix <- makeContrasts(HL60D1-HL60D0,
                                HL60D3-HL60D0,
                                HL60D7-HL60D0,
                                HL60D1-HL60D3,
                                HL60D1-HL60D7,
                                HL60D3-HL60D7,
                                levels = c("HL60D0","HL60D1","HL60D3","HL60D7"))
#will not be needed: don't keep big data
remove(normalized_data)
remove(normalized_data2)
remove(alive_data)

Please note that with this normalization, we are only using cells ????????????????(alive cells?)

General normalization

To be sure that the normalization is good I will continue the analysis with a more general normalization. The following is based on this page. By general I mean not specific to pikes.

data_dayDESeq <- as.character(meta_data$Population)
data_dayDESeq <- recode(data_dayDESeq, "HL60D0" = "Day 0", "HL60D1" = "Day 1", "HL60D3" = "Day 3", "HL60D7" = "Day 7")
data_dayDESeq <-factor(data_dayDESeq)
deSeqDat <- newCountDataSet(dataInitial, data_dayDESeq)
# Note: actually it's not a real normalisation. Rather computing size factors depending on ratio of medians 
# if all size factors are roughly equal to one, the libraries have been sequenced equally deeply.
deSeqDat <- estimateSizeFactors(deSeqDat)
head(sizeFactors(deSeqDat))
HL60D0.C01_S1 HL60D0.C02_S2 HL60D0.C03_S3 HL60D0.C04_S4 HL60D0.C05_S5 HL60D0.C06_S6 
    0.5254052     1.1318130     0.9646220     0.3233751     1.3896389     0.9596427 
idx.nz <- apply(counts(deSeqDat), 1, function(x) { all(x > 0)})
nNZsamples <- sum(idx.nz)
#will not be needed: don't keep big data
remove(dataInitial)

We see that the number of non zero samples in all genes is very low compared to traditional RNA-seq: 5 nomrally in thousands. This may be a good reason to stick with the normalization with skie RNA.

#plotting the estimated dispersions against the mean normalized counts
deSeqDat <- estimateDispersions(deSeqDat)
plotDispEsts(deSeqDat)

multidensity( counts(deSeqDat, normalized = T),xlab="mean counts", xlim=c(0, 1000))

 multiecdf( counts(deSeqDat, normalized = T),xlab="mean counts", xlim=c(0, 1000))

The two charts above clearly shows that the second normalisation isn’t convincing. Indeed, the second chart assesses whether the normalization has worked, and the densities should overlapp since most of the genes are heavily affected by the experimental conditions. Note: The strange density chart could also be due to the fact that miRNA are very rarely expressed in every sample (as we have seen before).

Plots

PCA

PCA no standardization

First we use a log transformation to make the data approximatively follow the homoscedasticity assumption.

#Log transform
log_normalized_data <- log(dataNZ)
log_normalized_data[log_normalized_data == "-Inf"] <- 0
data_pca <- prcomp(t(log_normalized_data))
g <- ggbiplot(data_pca, 
              scale = 1, 
              obs.scale = 1, 
              varname.abbrev = FALSE,
              var.axes = FALSE,
              pc.biplot =TRUE,
              circle = TRUE, 
              groups = data_day, 
              ellipse= TRUE) +
  ggtitle("PCA without standardizing") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 
g 

#will not be needed: don't keep big data
#remove(g)
remove(data_pca)
remove(log_normalized_data)

Note: The PCA graph is interesting as it shows that after each day the clusters seem to go down in PC2 and extend their variance in PC1.

PCA standardized

Knowing the importance of having standardized data for PCA, we could think of standarding ours. This in general is a good idea, as veraibles are often not on the same scale and thus cannot be compared directly. Here, on revanche we have dimensions that are comparable as they each represent the number of miRNA in each cell. It is therefore a good idea not to standrdize, as it will unnecessarily decrease the variance explained. More information on this can be found on the following forums: (here)[http://stats.stackexchange.com/questions/105592/not-normalizing-data-before-pca-gives-better-explained-variance-ratio] or (here)[http://stats.stackexchange.com/questions/69157/why-do-we-need-to-normalize-data-before-analysis]. Out of curiosity we will still plot the standardized data:

#Log transform
log_normalized_dataNZ <- log(dataNZ)
log_normalized_dataNZ[log_normalized_dataNZ == "-Inf"] <- 0
data_pcaNZ <- prcomp(t(log_normalized_dataNZ), center = TRUE, scale. = TRUE)
g <- ggbiplot(data_pcaNZ, 
              scale = 1, 
              obs.scale = 1, 
              varname.abbrev = FALSE,
              var.axes = FALSE,
              pc.biplot =TRUE,
              circle = TRUE, 
              groups = data_day, 
              ellipse= TRUE) +
  ggtitle("PCA non zero genes") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 
g 

#will not be needed: don't keep big data
#remove(g)
remove(data_pcaNZ)
remove(log_normalized_dataNZ)

From this plot we see that as we’ve supposed, the variance explained is lower than in the first one. We thus conclude that we should stick with the first plot as we can (because on the same scale).

PCA top 50

Let’s now plot the top 50 genes

#arranging data based on total expression
indexTopFifty <- sort(rowSums(n_data), index=T, decreasing=TRUE)$ix[1:50]
topFifty <- n_data[indexTopFifty,]
# note: small difference with kenny probably come from the fact that he did log before and then took top fifty 
#Log transform
log_topFifty <- log(topFifty)
log_topFifty[log_topFifty == "-Inf"] <- 0
#PCA
data_topFifty <- prcomp(t(log_topFifty))
g <- ggbiplot(data_topFifty, 
              scale = 1, 
              obs.scale = 1, 
              varname.abbrev = FALSE,
              var.axes = FALSE,
              pc.biplot =TRUE,
              circle = TRUE, 
              groups = data_day, 
              ellipse= TRUE) +
  ggtitle("PCA top 50 genes") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 
g

#will not be needed: don't keep big data
#remove(g)
remove(data_topFifty)
remove(log_topFifty)
remove(topFifty)

Correlation heatmap

# Note: both plots of dataNZ and full data gives same correlation heatmap
normalized_data_cor <- cor(dataNZ)  #calculating sample-sample correlations
scaled_normalized_data_cor <- scale(normalized_data_cor)  #scaling for better contrast
limit <- 2
scaled_normalized_data_cor[which(scaled_normalized_data_cor > limit)] <- limit    #trimming for better contrast
scaled_normalized_data_cor[which(scaled_normalized_data_cor < -limit)] <- -limit
mypal <- rev(colorRampPalette(brewer.pal(11,"RdBu"))(100)) #setting colour palette
alphabet <- c("#b2df8a","#33a02c","#ff7f00","#fdbf6f","#b15928","#1f78b4","#6a3d9a","#e31a1c","#a6cee3","#cab2d6","#ffff99","#fb9a99")
pops <- alphabet[as.factor(data_day)] #setting population colour palette
heatmap.2(scaled_normalized_data_cor, Rowv = NA, Colv = NA, symm = T, #making a heatmap
          trace = "none", dendrogram = "none", col = mypal,
          labCol = NA, labRow = NA,
          cexCol = 0.45, cexRow = 0.45, main = "Sample-Sample Correlations",
          ColSideColors = pops) 

#will not be needed: don't keep big data
remove(normalized_data_cor)
remove(scaled_normalized_data_cor)
#remove(heatmapPlot)

In this heat map we clearly see the high correlation between the samples of day 0 and 1 and between the samples of day 3 and 7.

t-SNE plots

General t-SNE

Let’s plot the t-SNE plots of the cells that aren’t dead to see if we can find clusters and / or outliers. Note that we aren’t taking into account genes that aren’t expressed in any samples.

# t-SNE plot with alive cells and non zero genes
#ordering data by expn
alive_tsne_data <- cbind(dataNZ, "avg_expn" = rowMeans(dataNZ), "miRNA" = row.names(dataNZ)) 
alive_tsne_data <- dplyr::arrange(alive_tsne_data,desc(avg_expn))
alive_tsne_data <- t(alive_tsne_data)
colnames(alive_tsne_data) <- alive_tsne_data["miRNA", ]
#removes rows that were added for ordering
alive_tsne_data <- alive_tsne_data[!rownames(alive_tsne_data) %in% c("miRNA","avg_expn"), ]
tsne_out <- Rtsne(dist(alive_tsne_data)) # Run TSNE
# Show the objects in the 2D tsne representation
tSNETotal <- qplot(x=tsne_out$Y[,1], y=tsne_out$Y[,2],color=data_day) + 
  labs(colour = "Cell Type", x = "tsne1", y = "tsne2")+
  ggtitle("t-SNE alive cells and non zero genes") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 
tSNETotal

#will not be needed: don't keep big data
remove(tsne_out)
#remove(tSNETotal)

As with the correlation heatmap, we see that the samples from day 0 and 1 are clustered together while those from day 3 and 7 are clustered together.

t-SNE of Day 0 and Day 1

Now that we have seen that the samples from day 0 and 1 are closely related. Let’s try to take only those 2 in order to see if we can separate them from each other.

#tsne on Day 0/Day 1 cells only
indexDay01 <- which(data_day %in% c("Day 0","Day 1"))
group_one_data <- alive_tsne_data[indexDay01, ] #selecting only day 0 and day 1 cells
tsne_out <- Rtsne(dist(group_one_data)) # Run TSNE
# Show the objects in the 2D tsne representation
tsneDay01 <- qplot(x=tsne_out$Y[,1], y=tsne_out$Y[,2],color=data_day[indexDay01]) +
  labs(colour = "Cell Type", x = "tsne1", y = "tsne2") +
  ggtitle("t-SNE only day 0 and 1") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 
tsneDay01

#will not be needed: don't keep big data
remove(tsne_out)
#remove(tsneDay01)

The t-SNE can clearly not separate the 2 samples from each other. Finally let’s investigate whether they can be separated with a t-SNE in 3 dimension:

tsne_out <- Rtsne(dist(group_one_data), dims = 3) # Run TSNE in 3 dimensions
plot_ly(x=tsne_out$Y[,1],
        y=tsne_out$Y[,2],
        z=tsne_out$Y[,3],
        type="scatter3d",
        color=data_day[indexDay01],
        mode="markers") %>% 
  layout(title = 't-SNE day 0 and 1 3D')

#will not be needed: don't keep big data
remove(tsne_out)
remove(group_one_data)
#remove(tsneDay01)

We can still not distinguish both type of cells. This really shows how similar they are.

t-SNE of Day 0 and Day 1

Now let’s look at the cluster Day 3 and 7, to see if they can be distinguished.

#tsne on Day 0/Day 1 cells only
indexDay37 <- which(data_day %in% c("Day 3","Day 7"))
group_two_data <- alive_tsne_data[indexDay37, ] #selecting only day 0 and day 1 cells
tsne_out <- Rtsne(dist(group_two_data)) # Run TSNE
# Show the objects in the 2D tsne representation
tsneDay37 <- qplot(x=tsne_out$Y[,1], y=tsne_out$Y[,2],color=data_day[indexDay37]) +
  labs(colour = "Cell Type", x = "tsne1", y = "tsne2") +
  ggtitle("t-SNE only day 3 and 7") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 
tsneDay37

#will not be needed: don't keep big data
remove(tsne_out)
#remove(tsneDay37)

As before, the 2 type of cells cannot be distinguished with a t-SNE plot in 2D. They will probably not be distinguishable in 3D but let’s be sure:

tsne_out <- Rtsne(dist(group_two_data), dims = 3) # Run TSNE in 3 dimensions
plot_ly(x=tsne_out$Y[,1],
        y=tsne_out$Y[,2],
        z=tsne_out$Y[,3],
        type="scatter3d",
        color=data_day[indexDay37],
        mode="markers") %>% 
  layout(title = 't-SNE day 3 and 7 3D')

#will not be needed: don't keep big data
remove(tsne_out)
remove(group_two_data)

Not suprisingly, the second cluster cannot be seprated further with 3 dimensional t-SNE.

Fit linear model

Note that for fitting linear models, we cannot use the DATASEQ library as it requires counts (i.e. discrete values). We now have continuous values because of they way we normalized the data.

Voom

Mean-Variance trend

First let us visualize the mean-variance trend, to see. Note: here it is important that we use only the genes with no non zero values for every sample as we can see in paragraph 15.3 of (limma manual)[https://www.bioconductor.org/packages/devel/bioc/vignettes/limma/inst/doc/usersguide.pdf]. From the same article they say that as a rule of thumb we should keep only genes that have a

#working ... HOW TO USE DATADESEQ ON NORMALIZED => NOT COUNTS ANY MORE?? + IS IT WORTH IT ? cAN we round ?
#dataDESeq <- rlog(as.matrix(data), blind=FALSE )
#makes a convenient dge object for analysis
#t <- n_data[which(rowSums(n_data) > 300),] 
dge <- DGEList(counts=dataNZ, group = data_day)
# applies TMM normalization to dge
#isExpr <- rowSums(dge$counts) > 1000
#dge <- dge[isExpr,]
dge <- calcNormFactors(dge)
data_voomed <- voom(dge,design,plot=TRUE)

#will not be needed: don't keep big data
remove(dge)

The mean-variance trend is suprising: it doesn’t look flat enough. The first hyporthesis we had is that we there was a problem because we normalize by samples and then limma does it again. But not normailizing our data doesn’t change the curve of the plot. We then thought that maybe limma was doing something that required discrete data (as it is made for count data), our data isn’t discrete as we normailized it based on spike RNA. But rounding the data doesn’t change anything either. We will have to look deeper at the meaning of te curve of the plot and whether our data doesn’t follow the Voom assumptions. Note that the data may also be strange due to the nature of miRNA data, indeed in RNAseq we often have high value of counts but in miRNA the number of counts are much lower. This could cause the spike we see below x = zero (i.e. very low mean).

We also see that the mean variance trend seam to be decreasing very quickly and steadily, we can thus conclude that the experiment seem to be of low biological variation. For more information please see the “Removing heteroscedascity from count data” subpart of (this paper)[https://f1000research.com/articles/5-1408]

Here is an example of the data we have:

data_voomed[1:2,1:10]
An object of class "EList"
$targets
               group  lib.size norm.factors
HL60D0.C01_S1  Day 0 100862.30    0.9833482
HL60D0.C02_S2  Day 0  68768.90    0.9420345
HL60D0.C03_S3  Day 0  60552.35    1.0147531
HL60D0.C04_S4  Day 0 279868.19    0.9569073
HL60D0.C05_S5  Day 0  65361.77    1.1399012
HL60D0.C06_S6  Day 0  36823.33    0.8372045
HL60D0.C07_S7  Day 0 127944.17    0.8744118
HL60D0.C08_S8  Day 0  51630.86    0.9873263
HL60D0.C09_S10 Day 0 217824.43    1.0843357
HL60D0.C10_S11 Day 0  55444.19    1.1485957

$E
              HL60D0.C01_S1 HL60D0.C02_S2 HL60D0.C03_S3 HL60D0.C04_S4 HL60D0.C05_S5 HL60D0.C06_S6
hsa-let-7a-5p     13.374469     12.879195      12.91583     7.6516046      13.06635      13.48863
hsa-let-7a-3p      2.309527      2.862079      10.11151     0.8371754      10.14368      10.50555
              HL60D0.C07_S7 HL60D0.C08_S8 HL60D0.C09_S10 HL60D0.C10_S11
hsa-let-7a-5p     13.102009      13.73708       12.72418      13.310086
hsa-let-7a-3p      1.966402      10.01462        9.35818       9.870383

$weights
          [,1]      [,2]      [,3]      [,4]      [,5]      [,6]      [,7]      [,8]      [,9]
[1,] 0.5885646 0.5004936 0.4749981 0.9426669 0.4901102 0.3899081 0.6533318 0.4453390 0.8348369
[2,] 0.2090121 0.1851257 0.1774882 0.2881312 0.1820762 0.1454568 0.2249386 0.1678079 0.2654087
         [,10]
[1,] 0.4582897
[2,] 0.1720934

$design
   HL60D0 HL60D1 HL60D3 HL60D7
1       1      0      0      0
2       1      0      0      0
3       1      0      0      0
4       1      0      0      0
5       1      0      0      0
6       1      0      0      0
7       1      0      0      0
8       1      0      0      0
9       1      0      0      0
10      1      0      0      0

Mean variance trend no log

Note: Seeing the strange plot above makes us think that maybe our count data doesn’t need to be log transformed. Let’s investigate the relationship between the mean and the variance of ou data.

#working ... HOW TO USE DATADESEQ ON NORMALIZED => NOT COUNTS ANY MORE?? + IS IT WORTH IT ? cAN we round ?
#dataDESeq <- rlog(as.matrix(data), blind=FALSE )
#takes only genes that are non zero in many samples
#t <- n_data[which(rowSums(n_data) > 300),] 
#tries plotting directly without voom
m <- rowMeans(dataNZ)
RowSigmaSqrt <- function(x) {
  (rowSums((x - rowMeans(x))^2)/(dim(x)[2] - 1))^(1/4)
}
v <- RowSigmaSqrt(dataNZ)
plotxy <- data.frame(mean=m,sigmaSqrt=v)
ggplot(plotxy, aes(x=mean, y=sigmaSqrt)) +
    geom_point(shape=1) +    # Use hollow circles
    geom_smooth(method=lm,   # Add linear regression line
                se=FALSE) + # Don't add shaded confidence region
  ylim(0, 7500) + 
  xlim(0,7500) + 
  ggtitle("Mean variance relationship not Voom") +
  theme(text = element_text(size=14),plot.title = element_text(hjust = 0.5)) 

From this plot we clearly see that our variance grows with fourth poqer of our mean. The reasoning behind this different relationship is still unclear to us (????????????? biologically), but it could indicate that we shouldn’t work with the default limma package and that we should maybe do the analysis manually (????????).

Fit linear model

fit <- lmFit(data_voomed, design)
fit <- contrasts.fit(fit, contrasts=contrastMatrix)
efit <- eBayes(fit)
topTable(efit, coef=colnames(coef(efit)))
plotSA(efit)

#will not be needed: don't keep big data
remove(fit)
remove(data_voomed)

Here there is a problem as we do not see the fitted line (?????).

Examining the number of DE genes

Let’s now look at differential expression levels of genes. Note that the adjusted p-value cutoff is 5%.

dt <- decideTests(efit)
summary(dt)
   HL60D1 - HL60D0 HL60D3 - HL60D0 HL60D7 - HL60D0 HL60D1 - HL60D3 HL60D1 - HL60D7
-1              28             325             498              87              41
0              705             376             206             292             221
1               11              43              40             365             482
   HL60D3 - HL60D7
-1              24
0              624
1               96

As we have already previously seen in the multiple plots of the previous section: most differential expressed genes are between day 0/1 and 3/7. We also note that a lot of genes in Day 3 and 7 are downregulated (compared to day 0 and 1).

Finding genes that are often differentially expressed compared to day 0

Let’s look at the genes that are always differentially expressed compared to day 0

# Finding genes that are not zero in every comparaison with day 0
commonDEgenesDay0 <- which(dt[,1]!=0 & dt[,2]!=0 & dt[,3]!=0)
names(commonDEgenesDay0)
 [1] "hsa-let-7a-3p"   "hsa-let-7b-3p"   "hsa-miR-1260a"   "hsa-miR-132-3p"  "hsa-miR-132-5p" 
 [6] "hsa-miR-143-3p"  "hsa-miR-17-3p"   "hsa-miR-181a-3p" "hsa-miR-181b-5p" "hsa-miR-181b-3p"
[11] "hsa-miR-199b-5p" "hsa-miR-19b-3p"  "hsa-miR-28-3p"   "hsa-miR-30d-5p"  "hsa-miR-5701"   
[16] "hsa-miR-7974"   

Let’s visualise it with a nice venn diagramm

vennDiagram(dt[,1:3], circle.col=c("turquoise", "salmon", "green"))

Finding genes that are often differentially between day 0/1 and day 3/7

Let’s look at the genes that are always differentially between day 0/1 and 3/7 as they seem to be the ones of interest.

# Finding genes that are not zero in every comparaison with day 0
commonDEgenesDay0137 <- which(dt[,2]!=0 & dt[,3]!=0 & dt[,4]!=0 & dt[,5]!=0)
names(commonDEgenesDay0137)
  [1] "hsa-let-7c-3p"     "hsa-let-7d-3p"     "hsa-let-7e-5p"     "hsa-let-7i-5p"    
  [5] "hsa-miR-101-3p"    "hsa-miR-106b-3p"   "hsa-miR-106b-5p"   "hsa-miR-1233-3p"  
  [9] "hsa-miR-1234-3p"   "hsa-miR-1236-3p"   "hsa-miR-125a-5p"   "hsa-miR-125b-2-3p"
 [13] "hsa-miR-1260a"     "hsa-miR-1268a"     "hsa-miR-1268b"     "hsa-miR-1271-5p"  
 [17] "hsa-miR-1271-3p"   "hsa-miR-1273d"     "hsa-miR-1273h-5p"  "hsa-miR-1275"     
 [21] "hsa-miR-1278"      "hsa-miR-1281"      "hsa-miR-1285-3p"   "hsa-miR-1287-5p"  
 [25] "hsa-miR-129-2-3p"  "hsa-miR-1291"      "hsa-miR-1303"      "hsa-miR-1304-3p"  
 [29] "hsa-miR-1306-3p"   "hsa-miR-1307-3p"   "hsa-miR-132-3p"    "hsa-miR-138-5p"   
 [33] "hsa-miR-143-5p"    "hsa-miR-143-3p"    "hsa-miR-145-5p"    "hsa-miR-146b-3p"  
 [37] "hsa-miR-149-5p"    "hsa-miR-150-5p"    "hsa-miR-151a-5p"   "hsa-miR-152-5p"   
 [41] "hsa-miR-1537-5p"   "hsa-miR-155-3p"    "hsa-miR-181a-3p"   "hsa-miR-181b-3p"  
 [45] "hsa-miR-181c-3p"   "hsa-miR-182-5p"    "hsa-miR-1827"      "hsa-miR-186-3p"   
 [49] "hsa-miR-190a-5p"   "hsa-miR-192-5p"    "hsa-miR-193a-5p"   "hsa-miR-193a-3p"  
 [53] "hsa-miR-195-5p"    "hsa-miR-196a-5p"   "hsa-miR-196b-5p"   "hsa-miR-197-5p"   
 [57] "hsa-miR-19b-3p"    "hsa-miR-200c-5p"   "hsa-miR-205-5p"    "hsa-miR-210-3p"   
 [61] "hsa-miR-2115-3p"   "hsa-miR-2116-3p"   "hsa-miR-212-3p"    "hsa-miR-218-5p"   
 [65] "hsa-miR-223-3p"    "hsa-miR-224-5p"    "hsa-miR-2277-3p"   "hsa-miR-2277-5p"  
 [69] "hsa-miR-2278"      "hsa-miR-23a-5p"    "hsa-miR-23a-3p"    "hsa-miR-25-3p"    
 [73] "hsa-miR-25-5p"     "hsa-miR-27a-5p"    "hsa-miR-29b-1-5p"  "hsa-miR-301b-5p"  
 [77] "hsa-miR-3074-3p"   "hsa-miR-3115"      "hsa-miR-3128"      "hsa-miR-3136-5p"  
 [81] "hsa-miR-3146"      "hsa-miR-3154"      "hsa-miR-3158-3p"   "hsa-miR-3173-3p"  
 [85] "hsa-miR-3177-3p"   "hsa-miR-3180-5p"   "hsa-miR-3181"      "hsa-miR-3198"     
 [89] "hsa-miR-328-3p"    "hsa-miR-338-5p"    "hsa-miR-33b-3p"    "hsa-miR-34a-5p"   
 [93] "hsa-miR-3529-3p"   "hsa-miR-3607-5p"   "hsa-miR-3607-3p"   "hsa-miR-3614-3p"  
 [97] "hsa-miR-3648"      "hsa-miR-365a-3p"   "hsa-miR-365b-3p"   "hsa-miR-3662"     
[101] "hsa-miR-3677-3p"   "hsa-miR-3680-5p"   "hsa-miR-3680-3p"   "hsa-miR-3691-5p"  
[105] "hsa-miR-378b"      "hsa-miR-378g"      "hsa-miR-3912-5p"   "hsa-miR-3913-5p"  
[109] "hsa-miR-3917"      "hsa-miR-3922-3p"   "hsa-miR-3940-3p"   "hsa-miR-3940-5p"  
[113] "hsa-miR-3942-5p"   "hsa-miR-3944-3p"   "hsa-miR-409-3p"    "hsa-miR-422a"     
[117] "hsa-miR-424-3p"    "hsa-miR-425-5p"    "hsa-miR-4284"      "hsa-miR-4421"     
[121] "hsa-miR-4426"      "hsa-miR-4429"      "hsa-miR-4434"      "hsa-miR-4435"     
[125] "hsa-miR-4449"      "hsa-miR-4454"      "hsa-miR-4477b"     "hsa-miR-4484"     
[129] "hsa-miR-450a-2-3p" "hsa-miR-4510"      "hsa-miR-4515"      "hsa-miR-4518"     
[133] "hsa-miR-4523"      "hsa-miR-455-5p"    "hsa-miR-4660"      "hsa-miR-4662a-5p" 
[137] "hsa-miR-4664-5p"   "hsa-miR-4685-3p"   "hsa-miR-4707-5p"   "hsa-miR-4723-5p"  
[141] "hsa-miR-4743-3p"   "hsa-miR-4744"      "hsa-miR-4745-5p"   "hsa-miR-4745-3p"  
[145] "hsa-miR-4747-3p"   "hsa-miR-4766-3p"   "hsa-miR-4772-3p"   "hsa-miR-4777-3p"  
[149] "hsa-miR-4779"      "hsa-miR-4782-3p"   "hsa-miR-4785"      "hsa-miR-4791"     
[153] "hsa-miR-4796-5p"   "hsa-miR-4797-3p"   "hsa-miR-4802-3p"   "hsa-miR-486-5p"   
[157] "hsa-miR-495-3p"    "hsa-miR-497-5p"    "hsa-miR-5001-5p"   "hsa-miR-5004-3p"  
[161] "hsa-miR-5094"      "hsa-miR-5188"      "hsa-miR-548a-3p"   "hsa-miR-548aa"    
[165] "hsa-miR-548ag"     "hsa-miR-548am-5p"  "hsa-miR-548ar-3p"  "hsa-miR-548au-3p" 
[169] "hsa-miR-548aw"     "hsa-miR-548ay-5p"  "hsa-miR-548b-5p"   "hsa-miR-548d-5p"  
[173] "hsa-miR-548f-3p"   "hsa-miR-548n"      "hsa-miR-548s"      "hsa-miR-548t-5p"  
[177] "hsa-miR-548t-3p"   "hsa-miR-550b-2-5p" "hsa-miR-552-5p"    "hsa-miR-5585-5p"  
[181] "hsa-miR-5586-5p"   "hsa-miR-5684"      "hsa-miR-5690"      "hsa-miR-570-3p"   
[185] "hsa-miR-573"       "hsa-miR-581"       "hsa-miR-582-5p"    "hsa-miR-597-3p"   
[189] "hsa-miR-6134"      "hsa-miR-617"       "hsa-miR-628-3p"    "hsa-miR-629-5p"   
[193] "hsa-miR-639"       "hsa-miR-6500-3p"   "hsa-miR-6509-5p"   "hsa-miR-6513-3p"  
[197] "hsa-miR-663a"      "hsa-miR-663b"      "hsa-miR-6724-5p"   "hsa-miR-6726-3p"  
[201] "hsa-miR-6727-5p"   "hsa-miR-6729-3p"   "hsa-miR-6730-5p"   "hsa-miR-6733-3p"  
[205] "hsa-miR-6734-3p"   "hsa-miR-6734-5p"   "hsa-miR-6735-3p"   "hsa-miR-6737-3p"  
[209] "hsa-miR-6749-3p"   "hsa-miR-6753-5p"   "hsa-miR-6754-3p"   "hsa-miR-6762-3p"  
[213] "hsa-miR-6763-5p"   "hsa-miR-6764-3p"   "hsa-miR-6764-5p"   "hsa-miR-6774-3p"  
[217] "hsa-miR-6777-3p"   "hsa-miR-6781-3p"   "hsa-miR-6781-5p"   "hsa-miR-6787-3p"  
[221] "hsa-miR-6790-3p"   "hsa-miR-6793-3p"   "hsa-miR-6797-3p"   "hsa-miR-6798-3p"  
[225] "hsa-miR-6803-3p"   "hsa-miR-6812-3p"   "hsa-miR-6813-5p"   "hsa-miR-6818-3p"  
[229] "hsa-miR-6819-3p"   "hsa-miR-6833-3p"   "hsa-miR-6837-5p"   "hsa-miR-6844"     
[233] "hsa-miR-6849-3p"   "hsa-miR-6852-5p"   "hsa-miR-6857-3p"   "hsa-miR-6858-5p"  
[237] "hsa-miR-6859-3p"   "hsa-miR-6862-3p"   "hsa-miR-6868-3p"   "hsa-miR-6873-3p"  
[241] "hsa-miR-6885-3p"   "hsa-miR-6889-3p"   "hsa-miR-6891-5p"   "hsa-miR-6891-3p"  
[245] "hsa-miR-6894-3p"   "hsa-miR-7111-3p"   "hsa-miR-7112-3p"   "hsa-miR-7114-3p"  
[249] "hsa-miR-7641"      "hsa-miR-766-5p"    "hsa-miR-7705"      "hsa-miR-7854-3p"  
[253] "hsa-miR-8485"      "hsa-miR-874-3p"    "hsa-miR-877-5p"    "hsa-miR-885-5p"   
[257] "hsa-miR-9-3p"      "hsa-miR-92a-1-5p"  "hsa-miR-92a-3p"    "hsa-miR-937-5p"   
[261] "hsa-miR-940"       "hsa-miR-942-3p"    "hsa-miR-99a-3p"   

Let’s visualise it with a nice venn diagramm

vennDiagram(dt[,2:5], circle.col=c("turquoise", "salmon", "green","yellow"))

LS0tCnRpdGxlOiAiU3VtbWFyeSB3b3JrIgphdXRob3I6ICJLZXZpbiBKZXBzb24sIFN0ZXBoYW5pZSBCbGFpbiwgTWFja2VuemllIEtpbm5leSwgR2FycmV0dCBNY0NhcnRoeSwgS2VubmV0aCBBc2tlbHNvbiBhbmQgWWFubiBEdWJvaXMiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB5ZXMKaGVhZGVyLWluY2x1ZGVzOiBcdXNlcGFja2FnZXthbXNtYXRofQotLS0KCiMgU2V0dGluZyB1cCB0aGUgZW52aXJvbm1lbnQKCmBgYHtyIGxvYWRpbmdfZGF0YSwgcmVzdWx0cz0naGlkZScsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiMgUGFja2FnZXMKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHBsb3RseSkKbGlicmFyeSh0aWR5cikKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkobGltbWEpCmxpYnJhcnkoZ3Bsb3RzKQpsaWJyYXJ5KGVkZ2VSKQpsaWJyYXJ5KGRldnRvb2xzKQpsaWJyYXJ5KGdnYmlwbG90KQpsaWJyYXJ5KERFU2VxKQpsaWJyYXJ5KGdlbmVwbG90dGVyKQpsaWJyYXJ5KFJ0c25lKQoKc2V0LnNlZWQoMTIzNCkgIyBtYWtlcyBldmVyeXRoaW5nIHJlcHJvZHVjdGlibGUgCgptZXRhX2RhdGEgPC0gcmVhZC50YWJsZSgiLi4vRGF0YS9yYXdfZGF0YS9tZXRhX2RhdGEudHh0IiwgaGVhZGVyID0gVFJVRSkKZGF0YUluaXRpYWwgPC0gcmVhZC50YWJsZSgiLi4vRGF0YS9yYXdfZGF0YS9leHBuX21hdHJpeC50eHQiLCBoZWFkZXIgPSBUUlVFLCByb3cubmFtZXMgPSAxKQpzcGlrZV9kYXRhIDwtIHJlYWQudGFibGUoIi4uL0RhdGEvcmF3X2RhdGEvZXhwbl9tYXRyaXhfc3Bpa2UudHh0IiwgaGVhZGVyID0gVFJVRSwgcm93Lm5hbWVzID0gMSkKYGBgCgojTm9ybWFsaXphdGlvbiAKCiMjS2V2aW4ncyBub3JtYWxpemF0aW9uCgpIZXJlIHRoZSBkYXRhIGlzIG5vcm1hbGl6ZWQgYmFzZWQgb24gdGhlIHNwaWtlX2RhdGEgd2UgaGF2ZS4gQWx0aG91Z2ggdGhpcyBzZWVtcyB0byBiZSBjb3JyZWN0LCB0aGVyZSBjb3VsZCBiZSBzb21lIGlzc3VlczogW1NlZSBwb3N0XShodHRwczovL3N1cHBvcnQuYmlvY29uZHVjdG9yLm9yZy9wLzc0ODcwLykuCgpgYGB7ciBub3JtYWxpemVfa2V2aW59CnNwaWtlX2RhdGEgPC0gcmJpbmQoc3Bpa2VfZGF0YSwgIlRvdGFscyIgPSBjb2xTdW1zKHNwaWtlX2RhdGEpKSAjZmluZGluZyBzdW0gb2YgY29sdW1uIGFuZCBhZGRpbmcgaXQgYXMgbmV3IHJvdwpzY2FsZWRfdG90YWxzIDwtIHNwaWtlX2RhdGFbIlRvdGFscyIsIF0KYXZlcmFnZV9yZWFkcyA8LSByb3dNZWFucyhzY2FsZWRfdG90YWxzKQpzY2FsZWRfdG90YWxzIDwtIHJiaW5kKHNjYWxlZF90b3RhbHMsICJTY2FsZSIgPSBzY2FsZWRfdG90YWxzWzEsIF0gLyBhdmVyYWdlX3JlYWRzKSAjZGl2aWRpbmcgdG90YWwgc3Bpa2UgdmFsdWVzIGJ5IGF2ZXJhZ2Ugc3Bpa2UgdmFsdWVzCgpkaW1fbmFtZXMgPC0gbGlzdChyb3cubmFtZXMoZGF0YUluaXRpYWwpKSAgICAgICAjc2V0dGluZyBkaW1fbmFtZXMgZm9yIHVwY29taW5nIG1hdHJpeApkaW1fbmFtZXNbMl0gPC0gbGlzdChjb2xuYW1lcygoZGF0YUluaXRpYWwpKSkKCm5vcm1hbGl6ZWRfZGF0YSA8LSBtYXRyaXgobnJvdyA9IG5yb3coZGF0YUluaXRpYWwpLCBuY29sID0gbmNvbChkYXRhSW5pdGlhbCksIGRpbW5hbWVzID0gZGltX25hbWVzKSAjcHJlLW1ha2luZyBhIG1hdHJpeAoKZm9yKGkgaW4gMTogbmNvbChkYXRhSW5pdGlhbCkpeyAgICNmb3IgbG9vcCB3aGljaCBzY2FsZXMgZGF0YSBhbmQgc2F2ZXMgaXQgYXMgbm9ybWFsaXplZF9kYXRhCiAgbm9ybWFsaXplZF9kYXRhWyAsIGldIDwtIGRhdGFJbml0aWFsWyAsIGldIC8gc2NhbGVkX3RvdGFsc1syLCBpXQp9Cm5vcm1hbGl6ZWRfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKG5vcm1hbGl6ZWRfZGF0YSkKCiNub3JtYWxpemluZyBmb3IgY2VsbCBzaXplIChjZWxsdWxhciBtaVJOQSBjb3VudHMpCnRvdGFsX2RhdGEgPC0gcmJpbmQoc3Bpa2VfZGF0YSwgIlRvdGFsIFNwaWtlIiA9IGNvbFN1bXMoc3Bpa2VfZGF0YSksICJUb3RhbCBSZWFkcyIgPSBjb2xTdW1zKGRhdGFJbml0aWFsKSkKdG90YWxfY2VsbHVsYXIgPC0gdG90YWxfZGF0YVsiVG90YWwgUmVhZHMiLCBdCmF2ZXJhZ2VfcmVhZHMgPC0gcm93TWVhbnModG90YWxfY2VsbHVsYXIpCmNlbGxfc2NhbGVzIDwtIHJiaW5kKHRvdGFsX2NlbGx1bGFyLCAiU2NhbGUiID0gdG90YWxfY2VsbHVsYXJbMSwgXSAvIGF2ZXJhZ2VfcmVhZHMpICNkaXZpZGluZyB0b3RhbCBzcGlrZSB2YWx1ZXMgYnkgYXZlcmFnZSBzcGlrZSB2YWx1ZXMKCmRpbV9uYW1lcyA8LSBsaXN0KHJvdy5uYW1lcyhkYXRhSW5pdGlhbCkpICAgICAgICNzZXR0aW5nIGRpbV9uYW1lcyBmb3IgdXBjb21pbmcgbWF0cml4CmRpbV9uYW1lc1syXSA8LSBsaXN0KGNvbG5hbWVzKChkYXRhSW5pdGlhbCkpKQoKbm9ybWFsaXplZF9kYXRhMiA8LSBtYXRyaXgobnJvdyA9IG5yb3coZGF0YUluaXRpYWwpLCBuY29sID0gbmNvbChkYXRhSW5pdGlhbCksIGRpbW5hbWVzID0gZGltX25hbWVzKSAjcHJlLW1ha2luZyBhIG1hdHJpeAoKZm9yKGkgaW4gMTogbmNvbChkYXRhSW5pdGlhbCkpeyAgICNmb3IgbG9vcCB3aGljaCBzY2FsZXMgZGF0YSBhbmQgc2F2ZXMgaXQgYXMgbm9ybWFsaXplZF9kYXRhCiAgbm9ybWFsaXplZF9kYXRhMlsgLCBpXSA8LSBub3JtYWxpemVkX2RhdGFbICwgaV0gLyBzY2FsZWRfdG90YWxzWzIsIGldCn0Kbm9ybWFsaXplZF9kYXRhMiA8LSBhcy5kYXRhLmZyYW1lKG5vcm1hbGl6ZWRfZGF0YTIpCgojIGRlbGV0aW5nIGRlYWQgY2VsbHMKCmFsaXZlX2luZGV4ZXMgPC0gbGlzdCgpICNpbml0aWFsaXppbmcgbGlzdHMKayA8LSAxICAjaW5pdGlhbGl6aW5nIGNvdW50ZXIKZm9yKGkgaW4gMTpuY29sKHRvdGFsX2RhdGEpKXsKICBpZih0b3RhbF9kYXRhWyJUb3RhbCBSZWFkcyIsIGldID4gMjAwMDApewogICAgYWxpdmVfaW5kZXhlc1trXSA8LSBpCiAgICBrIDwtIGsgKyAxCiAgfQp9CgphbGl2ZV9kYXRhIDwtIG5vcm1hbGl6ZWRfZGF0YTJbICwgYXMubnVtZXJpYyhhbGl2ZV9pbmRleGVzKV0KYWxpdmVfbWV0YV9kYXRhIDwtIG1ldGFfZGF0YVthcy5udW1lcmljKGFsaXZlX2luZGV4ZXMpLCBdCgojU2F2aW5nIGNvbXBsZXRlbHkgbm9ybWFsaXplZCBkYXRhIGFzIG5fZGF0YSBhbmQgbl9tZXRhX2RhdGEKbl9kYXRhIDwtIGFsaXZlX2RhdGEKbl9tZXRhX2RhdGEgPC0gYWxpdmVfbWV0YV9kYXRhCgojbWFrZXMgZ3JvdXAgYW5kIGRlc2lnbiBtYXRyaXgKZGF0YV9kYXkgPC0gYXMuY2hhcmFjdGVyKG5fbWV0YV9kYXRhJFBvcHVsYXRpb24pCmRhdGFfZGF5IDwtIHJlY29kZShkYXRhX2RheSwgIkhMNjBEMCIgPSAiRGF5IDAiLCAiSEw2MEQxIiA9ICJEYXkgMSIsICJITDYwRDMiID0gIkRheSAzIiwgIkhMNjBENyIgPSAiRGF5IDciKQpkYXRhX2RheSA8LWZhY3RvcihkYXRhX2RheSkKCmRlc2lnbiA8LSBtb2RlbC5tYXRyaXgofjAgKyBuX21ldGFfZGF0YSRQb3B1bGF0aW9uKQojZGVsZXRlcyAibl9tZXRhX2RhdGEkUG9wdWxhdGlvbiIgZnJvbSBuYW1lIG9mIGNvbHVtbnMKY29sbmFtZXMoZGVzaWduKSA8LSBnc3ViKCJuX21ldGFfZGF0YVxcJFBvcHVsYXRpb24iLCAiIiwgY29sbmFtZXMoZGVzaWduKSkKI2xldHMgY2FsbCBpbnRlcmNlcHQgSEw2MEQwCiNjb2xuYW1lcyhkZXNpZ24pWzFdIDwtICJITDYwRDAiCgojIEtlZXBzIGdlbmVzIHdpdGhvdXQgYWxsIHplcm9zIG1pUk5BCmRhdGFOWiA8LSBuX2RhdGFbd2hpY2gocm93U3VtcyhuX2RhdGEpID4gMCksXSAKCiNtYWtpbmcgdGhlIGNvbnRyYXN0IG1hdHJpeAojIGxldCdzIHN1cHBvc2UgZm9yIG5vdyB0aGF0IHdlIHdhbnQgdG8gY29tcGFyZSBlYWNoIGdyb3VwIHdpdGggZWFjaCBvdGhlciA/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/Pz8/CmNvbnRyYXN0TWF0cml4IDwtIG1ha2VDb250cmFzdHMoSEw2MEQxLUhMNjBEMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBITDYwRDMtSEw2MEQwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhMNjBENy1ITDYwRDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSEw2MEQxLUhMNjBEMywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBITDYwRDEtSEw2MEQ3LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhMNjBEMy1ITDYwRDcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiSEw2MEQwIiwiSEw2MEQxIiwiSEw2MEQzIiwiSEw2MEQ3IikpCgojd2lsbCBub3QgYmUgbmVlZGVkOiBkb24ndCBrZWVwIGJpZyBkYXRhCnJlbW92ZShub3JtYWxpemVkX2RhdGEpCnJlbW92ZShub3JtYWxpemVkX2RhdGEyKQpyZW1vdmUoYWxpdmVfZGF0YSkKYGBgCgpQbGVhc2Ugbm90ZSB0aGF0IHdpdGggdGhpcyBub3JtYWxpemF0aW9uLCB3ZSBhcmUgb25seSB1c2luZyBjZWxscyA/Pz8/Pz8/Pz8/Pz8/Pz8/KGFsaXZlIGNlbGxzPykKCiMjR2VuZXJhbCBub3JtYWxpemF0aW9uIAoKVG8gYmUgc3VyZSB0aGF0IHRoZSBub3JtYWxpemF0aW9uIGlzIGdvb2QgSSB3aWxsIGNvbnRpbnVlIHRoZSBhbmFseXNpcyB3aXRoIGEgbW9yZSBnZW5lcmFsIG5vcm1hbGl6YXRpb24uIFRoZSBmb2xsb3dpbmcgaXMgYmFzZWQgb24gW3RoaXMgcGFnZV0oaHR0cDovL3d3dy1odWJlci5lbWJsLmRlL3VzZXJzL2tsYXVzL1RlYWNoaW5nL0RFU2VxMlByZWRvYzIwMTQuaHRtbCNwY2EtYW5kLXNhbXBsZS1oZWF0bWFwcykuIEJ5IGdlbmVyYWwgSSBtZWFuIG5vdCBzcGVjaWZpYyB0byBwaWtlcy4KCmBgYHtyIG5vcm1hbGl6ZV9ERVNlcX0KZGF0YV9kYXlERVNlcSA8LSBhcy5jaGFyYWN0ZXIobWV0YV9kYXRhJFBvcHVsYXRpb24pCmRhdGFfZGF5REVTZXEgPC0gcmVjb2RlKGRhdGFfZGF5REVTZXEsICJITDYwRDAiID0gIkRheSAwIiwgIkhMNjBEMSIgPSAiRGF5IDEiLCAiSEw2MEQzIiA9ICJEYXkgMyIsICJITDYwRDciID0gIkRheSA3IikKZGF0YV9kYXlERVNlcSA8LWZhY3RvcihkYXRhX2RheURFU2VxKQoKZGVTZXFEYXQgPC0gbmV3Q291bnREYXRhU2V0KGRhdGFJbml0aWFsLCBkYXRhX2RheURFU2VxKQoKIyBOb3RlOiBhY3R1YWxseSBpdCdzIG5vdCBhIHJlYWwgbm9ybWFsaXNhdGlvbi4gUmF0aGVyIGNvbXB1dGluZyBzaXplIGZhY3RvcnMgZGVwZW5kaW5nIG9uIHJhdGlvIG9mIG1lZGlhbnMgCiMgaWYgYWxsIHNpemUgZmFjdG9ycyBhcmUgcm91Z2hseSBlcXVhbCB0byBvbmUsIHRoZSBsaWJyYXJpZXMgaGF2ZSBiZWVuIHNlcXVlbmNlZCBlcXVhbGx5IGRlZXBseS4KCmRlU2VxRGF0IDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZGVTZXFEYXQpCmhlYWQoc2l6ZUZhY3RvcnMoZGVTZXFEYXQpKQoKaWR4Lm56IDwtIGFwcGx5KGNvdW50cyhkZVNlcURhdCksIDEsIGZ1bmN0aW9uKHgpIHsgYWxsKHggPiAwKX0pCm5OWnNhbXBsZXMgPC0gc3VtKGlkeC5ueikKCiN3aWxsIG5vdCBiZSBuZWVkZWQ6IGRvbid0IGtlZXAgYmlnIGRhdGEKcmVtb3ZlKGRhdGFJbml0aWFsKQpgYGAKCldlIHNlZSB0aGF0IHRoZSBudW1iZXIgb2Ygbm9uIHplcm8gc2FtcGxlcyBpbiBhbGwgZ2VuZXMgaXMgdmVyeSBsb3cgY29tcGFyZWQgdG8gdHJhZGl0aW9uYWwgUk5BLXNlcTogYHIgbk5ac2FtcGxlc2Agbm9tcmFsbHkgaW4gdGhvdXNhbmRzLiBUaGlzIG1heSBiZSBhIGdvb2QgcmVhc29uIHRvIHN0aWNrIHdpdGggdGhlIG5vcm1hbGl6YXRpb24gd2l0aCBza2llIFJOQS4KCmBgYHtyIHBsb3R0X2Rpc3BlcnNpb259CiNwbG90dGluZyB0aGUgZXN0aW1hdGVkIGRpc3BlcnNpb25zIGFnYWluc3QgdGhlIG1lYW4gbm9ybWFsaXplZCBjb3VudHMKZGVTZXFEYXQgPC0gZXN0aW1hdGVEaXNwZXJzaW9ucyhkZVNlcURhdCkKcGxvdERpc3BFc3RzKGRlU2VxRGF0KQptdWx0aWRlbnNpdHkoIGNvdW50cyhkZVNlcURhdCwgbm9ybWFsaXplZCA9IFQpLHhsYWI9Im1lYW4gY291bnRzIiwgeGxpbT1jKDAsIDEwMDApKQpgYGAKCmBgYHtyIHBsb3R0X2RlbnNpdHl9CiBtdWx0aWVjZGYoIGNvdW50cyhkZVNlcURhdCwgbm9ybWFsaXplZCA9IFQpLHhsYWI9Im1lYW4gY291bnRzIiwgeGxpbT1jKDAsIDEwMDApKQpgYGAKClRoZSB0d28gY2hhcnRzIGFib3ZlIGNsZWFybHkgc2hvd3MgdGhhdCB0aGUgc2Vjb25kIG5vcm1hbGlzYXRpb24gaXNuJ3QgY29udmluY2luZy4gSW5kZWVkLCB0aGUgc2Vjb25kIGNoYXJ0IGFzc2Vzc2VzIHdoZXRoZXIgdGhlIG5vcm1hbGl6YXRpb24gaGFzIHdvcmtlZCwgYW5kIHRoZSBkZW5zaXRpZXMgc2hvdWxkIG92ZXJsYXBwIHNpbmNlIG1vc3Qgb2YgdGhlIGdlbmVzIGFyZSBoZWF2aWx5IGFmZmVjdGVkIGJ5IHRoZSBleHBlcmltZW50YWwgY29uZGl0aW9ucy4gTm90ZTogVGhlIHN0cmFuZ2UgZGVuc2l0eSBjaGFydCBjb3VsZCBhbHNvIGJlIGR1ZSB0byB0aGUgZmFjdCB0aGF0IG1pUk5BIGFyZSB2ZXJ5IHJhcmVseSBleHByZXNzZWQgaW4gZXZlcnkgc2FtcGxlIChhcyB3ZSBoYXZlIHNlZW4gYmVmb3JlKS4KCgojIFBsb3RzCgojIyBQQ0EKCiMjIyBQQ0Egbm8gc3RhbmRhcmRpemF0aW9uCgpGaXJzdCB3ZSB1c2UgYSBsb2cgdHJhbnNmb3JtYXRpb24gdG8gbWFrZSB0aGUgZGF0YSBhcHByb3hpbWF0aXZlbHkgZm9sbG93IHRoZSBob21vc2NlZGFzdGljaXR5IGFzc3VtcHRpb24uIApgYGB7ciBQQ0F9CiNMb2cgdHJhbnNmb3JtCmxvZ19ub3JtYWxpemVkX2RhdGEgPC0gbG9nKGRhdGFOWikKbG9nX25vcm1hbGl6ZWRfZGF0YVtsb2dfbm9ybWFsaXplZF9kYXRhID09ICItSW5mIl0gPC0gMAoKZGF0YV9wY2EgPC0gcHJjb21wKHQobG9nX25vcm1hbGl6ZWRfZGF0YSkpCmcgPC0gZ2diaXBsb3QoZGF0YV9wY2EsIAogICAgICAgICAgICAgIHNjYWxlID0gMSwgCiAgICAgICAgICAgICAgb2JzLnNjYWxlID0gMSwgCiAgICAgICAgICAgICAgdmFybmFtZS5hYmJyZXYgPSBGQUxTRSwKICAgICAgICAgICAgICB2YXIuYXhlcyA9IEZBTFNFLAogICAgICAgICAgICAgIHBjLmJpcGxvdCA9VFJVRSwKICAgICAgICAgICAgICBjaXJjbGUgPSBUUlVFLCAKICAgICAgICAgICAgICBncm91cHMgPSBkYXRhX2RheSwgCiAgICAgICAgICAgICAgZWxsaXBzZT0gVFJVRSkgKwogIGdndGl0bGUoIlBDQSB3aXRob3V0IHN0YW5kYXJkaXppbmciKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSxwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgCgpnIAoKI3dpbGwgbm90IGJlIG5lZWRlZDogZG9uJ3Qga2VlcCBiaWcgZGF0YQojcmVtb3ZlKGcpCnJlbW92ZShkYXRhX3BjYSkKcmVtb3ZlKGxvZ19ub3JtYWxpemVkX2RhdGEpCmBgYApOb3RlOiBUaGUgUENBIGdyYXBoIGlzIGludGVyZXN0aW5nIGFzIGl0IHNob3dzIHRoYXQgYWZ0ZXIgZWFjaCBkYXkgdGhlIGNsdXN0ZXJzIHNlZW0gdG8gZ28gZG93biBpbiBQQzIgYW5kIGV4dGVuZCB0aGVpciB2YXJpYW5jZSBpbiBQQzEuCgojIyMgUENBIHN0YW5kYXJkaXplZAoKS25vd2luZyB0aGUgaW1wb3J0YW5jZSBvZiBoYXZpbmcgc3RhbmRhcmRpemVkIGRhdGEgZm9yIFBDQSwgd2UgY291bGQgdGhpbmsgb2Ygc3RhbmRhcmRpbmcgb3Vycy4gVGhpcyBpbiBnZW5lcmFsIGlzIGEgZ29vZCBpZGVhLCBhcyB2ZXJhaWJsZXMgYXJlIG9mdGVuIG5vdCBvbiB0aGUgc2FtZSBzY2FsZSBhbmQgdGh1cyBjYW5ub3QgYmUgY29tcGFyZWQgZGlyZWN0bHkuIEhlcmUsIG9uIHJldmFuY2hlIHdlIGhhdmUgZGltZW5zaW9ucyB0aGF0IGFyZSBjb21wYXJhYmxlIGFzIHRoZXkgZWFjaCByZXByZXNlbnQgdGhlIG51bWJlciBvZiBtaVJOQSBpbiBlYWNoIGNlbGwuIEl0IGlzIHRoZXJlZm9yZSBhIGdvb2QgaWRlYSBub3QgdG8gc3RhbmRyZGl6ZSwgYXMgaXQgd2lsbCB1bm5lY2Vzc2FyaWx5IGRlY3JlYXNlIHRoZSB2YXJpYW5jZSBleHBsYWluZWQuIE1vcmUgaW5mb3JtYXRpb24gb24gdGhpcyBjYW4gYmUgZm91bmQgb24gdGhlIGZvbGxvd2luZyBmb3J1bXM6IChoZXJlKVtodHRwOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzEwNTU5Mi9ub3Qtbm9ybWFsaXppbmctZGF0YS1iZWZvcmUtcGNhLWdpdmVzLWJldHRlci1leHBsYWluZWQtdmFyaWFuY2UtcmF0aW9dIG9yIChoZXJlKVtodHRwOi8vc3RhdHMuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzY5MTU3L3doeS1kby13ZS1uZWVkLXRvLW5vcm1hbGl6ZS1kYXRhLWJlZm9yZS1hbmFseXNpc10uIE91dCBvZiBjdXJpb3NpdHkgd2Ugd2lsbCBzdGlsbCBwbG90IHRoZSBzdGFuZGFyZGl6ZWQgZGF0YToKCmBgYHtyIFBDQV9OWn0KI0xvZyB0cmFuc2Zvcm0KbG9nX25vcm1hbGl6ZWRfZGF0YU5aIDwtIGxvZyhkYXRhTlopCmxvZ19ub3JtYWxpemVkX2RhdGFOWltsb2dfbm9ybWFsaXplZF9kYXRhTlogPT0gIi1JbmYiXSA8LSAwCgpkYXRhX3BjYU5aIDwtIHByY29tcCh0KGxvZ19ub3JtYWxpemVkX2RhdGFOWiksIGNlbnRlciA9IFRSVUUsIHNjYWxlLiA9IFRSVUUpCmcgPC0gZ2diaXBsb3QoZGF0YV9wY2FOWiwgCiAgICAgICAgICAgICAgc2NhbGUgPSAxLCAKICAgICAgICAgICAgICBvYnMuc2NhbGUgPSAxLCAKICAgICAgICAgICAgICB2YXJuYW1lLmFiYnJldiA9IEZBTFNFLAogICAgICAgICAgICAgIHZhci5heGVzID0gRkFMU0UsCiAgICAgICAgICAgICAgcGMuYmlwbG90ID1UUlVFLAogICAgICAgICAgICAgIGNpcmNsZSA9IFRSVUUsIAogICAgICAgICAgICAgIGdyb3VwcyA9IGRhdGFfZGF5LCAKICAgICAgICAgICAgICBlbGxpcHNlPSBUUlVFKSArCiAgZ2d0aXRsZSgiUENBIG5vbiB6ZXJvIGdlbmVzIikgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpIAoKZyAKCiN3aWxsIG5vdCBiZSBuZWVkZWQ6IGRvbid0IGtlZXAgYmlnIGRhdGEKI3JlbW92ZShnKQpyZW1vdmUoZGF0YV9wY2FOWikKcmVtb3ZlKGxvZ19ub3JtYWxpemVkX2RhdGFOWikKYGBgCgpGcm9tIHRoaXMgcGxvdCB3ZSBzZWUgdGhhdCBhcyB3ZSd2ZSBzdXBwb3NlZCwgdGhlIHZhcmlhbmNlIGV4cGxhaW5lZCBpcyBsb3dlciB0aGFuIGluIHRoZSBmaXJzdCBvbmUuIFdlIHRodXMgY29uY2x1ZGUgdGhhdCB3ZSBzaG91bGQgc3RpY2sgd2l0aCB0aGUgZmlyc3QgcGxvdCBhcyB3ZSBjYW4gKGJlY2F1c2Ugb24gdGhlIHNhbWUgc2NhbGUpLgoKIyMjIFBDQSB0b3AgNTAgCgpMZXQncyBub3cgcGxvdCB0aGUgdG9wIDUwIGdlbmVzCgpgYGB7ciBQQ0FfdG9wNTB9CiNhcnJhbmdpbmcgZGF0YSBiYXNlZCBvbiB0b3RhbCBleHByZXNzaW9uCmluZGV4VG9wRmlmdHkgPC0gc29ydChyb3dTdW1zKG5fZGF0YSksIGluZGV4PVQsIGRlY3JlYXNpbmc9VFJVRSkkaXhbMTo1MF0KdG9wRmlmdHkgPC0gbl9kYXRhW2luZGV4VG9wRmlmdHksXQojIG5vdGU6IHNtYWxsIGRpZmZlcmVuY2Ugd2l0aCBrZW5ueSBwcm9iYWJseSBjb21lIGZyb20gdGhlIGZhY3QgdGhhdCBoZSBkaWQgbG9nIGJlZm9yZSBhbmQgdGhlbiB0b29rIHRvcCBmaWZ0eSAKCiNMb2cgdHJhbnNmb3JtCmxvZ190b3BGaWZ0eSA8LSBsb2codG9wRmlmdHkpCmxvZ190b3BGaWZ0eVtsb2dfdG9wRmlmdHkgPT0gIi1JbmYiXSA8LSAwCgojUENBCmRhdGFfdG9wRmlmdHkgPC0gcHJjb21wKHQobG9nX3RvcEZpZnR5KSkKZyA8LSBnZ2JpcGxvdChkYXRhX3RvcEZpZnR5LCAKICAgICAgICAgICAgICBzY2FsZSA9IDEsIAogICAgICAgICAgICAgIG9icy5zY2FsZSA9IDEsIAogICAgICAgICAgICAgIHZhcm5hbWUuYWJicmV2ID0gRkFMU0UsCiAgICAgICAgICAgICAgdmFyLmF4ZXMgPSBGQUxTRSwKICAgICAgICAgICAgICBwYy5iaXBsb3QgPVRSVUUsCiAgICAgICAgICAgICAgY2lyY2xlID0gVFJVRSwgCiAgICAgICAgICAgICAgZ3JvdXBzID0gZGF0YV9kYXksIAogICAgICAgICAgICAgIGVsbGlwc2U9IFRSVUUpICsKICBnZ3RpdGxlKCJQQ0EgdG9wIDUwIGdlbmVzIikgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpIAoKZwoKI3dpbGwgbm90IGJlIG5lZWRlZDogZG9uJ3Qga2VlcCBiaWcgZGF0YQojcmVtb3ZlKGcpCnJlbW92ZShkYXRhX3RvcEZpZnR5KQpyZW1vdmUobG9nX3RvcEZpZnR5KQpyZW1vdmUodG9wRmlmdHkpCmBgYAoKIyMgQ29ycmVsYXRpb24gaGVhdG1hcApgYGB7ciBjb3JyZWxhdGlvbl9oZWF0bWFwfQojIE5vdGU6IGJvdGggcGxvdHMgb2YgZGF0YU5aIGFuZCBmdWxsIGRhdGEgZ2l2ZXMgc2FtZSBjb3JyZWxhdGlvbiBoZWF0bWFwCm5vcm1hbGl6ZWRfZGF0YV9jb3IgPC0gY29yKGRhdGFOWikgICNjYWxjdWxhdGluZyBzYW1wbGUtc2FtcGxlIGNvcnJlbGF0aW9ucwpzY2FsZWRfbm9ybWFsaXplZF9kYXRhX2NvciA8LSBzY2FsZShub3JtYWxpemVkX2RhdGFfY29yKSAgI3NjYWxpbmcgZm9yIGJldHRlciBjb250cmFzdAoKbGltaXQgPC0gMgpzY2FsZWRfbm9ybWFsaXplZF9kYXRhX2Nvclt3aGljaChzY2FsZWRfbm9ybWFsaXplZF9kYXRhX2NvciA+IGxpbWl0KV0gPC0gbGltaXQgICAgI3RyaW1taW5nIGZvciBiZXR0ZXIgY29udHJhc3QKc2NhbGVkX25vcm1hbGl6ZWRfZGF0YV9jb3Jbd2hpY2goc2NhbGVkX25vcm1hbGl6ZWRfZGF0YV9jb3IgPCAtbGltaXQpXSA8LSAtbGltaXQKCm15cGFsIDwtIHJldihjb2xvclJhbXBQYWxldHRlKGJyZXdlci5wYWwoMTEsIlJkQnUiKSkoMTAwKSkgI3NldHRpbmcgY29sb3VyIHBhbGV0dGUKYWxwaGFiZXQgPC0gYygiI2IyZGY4YSIsIiMzM2EwMmMiLCIjZmY3ZjAwIiwiI2ZkYmY2ZiIsIiNiMTU5MjgiLCIjMWY3OGI0IiwiIzZhM2Q5YSIsIiNlMzFhMWMiLCIjYTZjZWUzIiwiI2NhYjJkNiIsIiNmZmZmOTkiLCIjZmI5YTk5IikKcG9wcyA8LSBhbHBoYWJldFthcy5mYWN0b3IoZGF0YV9kYXkpXSAjc2V0dGluZyBwb3B1bGF0aW9uIGNvbG91ciBwYWxldHRlCgpoZWF0bWFwLjIoc2NhbGVkX25vcm1hbGl6ZWRfZGF0YV9jb3IsIFJvd3YgPSBOQSwgQ29sdiA9IE5BLCBzeW1tID0gVCwgI21ha2luZyBhIGhlYXRtYXAKICAgICAgICAgIHRyYWNlID0gIm5vbmUiLCBkZW5kcm9ncmFtID0gIm5vbmUiLCBjb2wgPSBteXBhbCwKICAgICAgICAgIGxhYkNvbCA9IE5BLCBsYWJSb3cgPSBOQSwKICAgICAgICAgIGNleENvbCA9IDAuNDUsIGNleFJvdyA9IDAuNDUsIG1haW4gPSAiU2FtcGxlLVNhbXBsZSBDb3JyZWxhdGlvbnMiLAogICAgICAgICAgQ29sU2lkZUNvbG9ycyA9IHBvcHMpIAoKI3dpbGwgbm90IGJlIG5lZWRlZDogZG9uJ3Qga2VlcCBiaWcgZGF0YQpyZW1vdmUobm9ybWFsaXplZF9kYXRhX2NvcikKcmVtb3ZlKHNjYWxlZF9ub3JtYWxpemVkX2RhdGFfY29yKQojcmVtb3ZlKGhlYXRtYXBQbG90KQpgYGAKCkluIHRoaXMgaGVhdCBtYXAgd2UgY2xlYXJseSBzZWUgdGhlIGhpZ2ggY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgc2FtcGxlcyBvZiBkYXkgMCBhbmQgMSBhbmQgYmV0d2VlbiB0aGUgc2FtcGxlcyBvZiBkYXkgMyBhbmQgNy4KCgojIyB0LVNORSBwbG90cwoKIyMjIEdlbmVyYWwgdC1TTkUKCkxldCdzIHBsb3QgdGhlIHQtU05FIHBsb3RzIG9mIHRoZSBjZWxscyB0aGF0IGFyZW4ndCBkZWFkIHRvIHNlZSBpZiB3ZSBjYW4gZmluZCBjbHVzdGVycyBhbmQgLyBvciBvdXRsaWVycy4gTm90ZSB0aGF0IHdlIGFyZW4ndCB0YWtpbmcgaW50byBhY2NvdW50IGdlbmVzIHRoYXQgYXJlbid0IGV4cHJlc3NlZCBpbiBhbnkgc2FtcGxlcy4KYGBge3IgdHNuZV9HZW5lcmFsfQojIHQtU05FIHBsb3Qgd2l0aCBhbGl2ZSBjZWxscyBhbmQgbm9uIHplcm8gZ2VuZXMKI29yZGVyaW5nIGRhdGEgYnkgZXhwbgphbGl2ZV90c25lX2RhdGEgPC0gY2JpbmQoZGF0YU5aLCAiYXZnX2V4cG4iID0gcm93TWVhbnMoZGF0YU5aKSwgIm1pUk5BIiA9IHJvdy5uYW1lcyhkYXRhTlopKSAKYWxpdmVfdHNuZV9kYXRhIDwtIGRwbHlyOjphcnJhbmdlKGFsaXZlX3RzbmVfZGF0YSxkZXNjKGF2Z19leHBuKSkKYWxpdmVfdHNuZV9kYXRhIDwtIHQoYWxpdmVfdHNuZV9kYXRhKQpjb2xuYW1lcyhhbGl2ZV90c25lX2RhdGEpIDwtIGFsaXZlX3RzbmVfZGF0YVsibWlSTkEiLCBdCiNyZW1vdmVzIHJvd3MgdGhhdCB3ZXJlIGFkZGVkIGZvciBvcmRlcmluZwphbGl2ZV90c25lX2RhdGEgPC0gYWxpdmVfdHNuZV9kYXRhWyFyb3duYW1lcyhhbGl2ZV90c25lX2RhdGEpICVpbiUgYygibWlSTkEiLCJhdmdfZXhwbiIpLCBdCgp0c25lX291dCA8LSBSdHNuZShkaXN0KGFsaXZlX3RzbmVfZGF0YSkpICMgUnVuIFRTTkUKIyBTaG93IHRoZSBvYmplY3RzIGluIHRoZSAyRCB0c25lIHJlcHJlc2VudGF0aW9uCnRTTkVUb3RhbCA8LSBxcGxvdCh4PXRzbmVfb3V0JFlbLDFdLCB5PXRzbmVfb3V0JFlbLDJdLGNvbG9yPWRhdGFfZGF5KSArIAogIGxhYnMoY29sb3VyID0gIkNlbGwgVHlwZSIsIHggPSAidHNuZTEiLCB5ID0gInRzbmUyIikrCiAgZ2d0aXRsZSgidC1TTkUgYWxpdmUgY2VsbHMgYW5kIG5vbiB6ZXJvIGdlbmVzIikgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpIAoKdFNORVRvdGFsCgojd2lsbCBub3QgYmUgbmVlZGVkOiBkb24ndCBrZWVwIGJpZyBkYXRhCnJlbW92ZSh0c25lX291dCkKI3JlbW92ZSh0U05FVG90YWwpCmBgYAoKQXMgd2l0aCB0aGUgY29ycmVsYXRpb24gaGVhdG1hcCwgd2Ugc2VlIHRoYXQgIHRoZSBzYW1wbGVzIGZyb20gZGF5IDAgYW5kIDEgYXJlIGNsdXN0ZXJlZCB0b2dldGhlciB3aGlsZSB0aG9zZSBmcm9tIGRheSAzIGFuZCA3IGFyZSBjbHVzdGVyZWQgdG9nZXRoZXIuCgojIyMgdC1TTkUgb2YgRGF5IDAgYW5kIERheSAxCgpOb3cgdGhhdCB3ZSBoYXZlIHNlZW4gdGhhdCB0aGUgc2FtcGxlcyBmcm9tIGRheSAwIGFuZCAxIGFyZSBjbG9zZWx5IHJlbGF0ZWQuIExldCdzIHRyeSB0byB0YWtlIG9ubHkgdGhvc2UgMiBpbiBvcmRlciB0byBzZWUgaWYgd2UgY2FuIHNlcGFyYXRlIHRoZW0gZnJvbSBlYWNoIG90aGVyLiAKCmBgYHtyIHRzbmVfZGF5MDF9CiN0c25lIG9uIERheSAwL0RheSAxIGNlbGxzIG9ubHkKaW5kZXhEYXkwMSA8LSB3aGljaChkYXRhX2RheSAlaW4lIGMoIkRheSAwIiwiRGF5IDEiKSkKZ3JvdXBfb25lX2RhdGEgPC0gYWxpdmVfdHNuZV9kYXRhW2luZGV4RGF5MDEsIF0gI3NlbGVjdGluZyBvbmx5IGRheSAwIGFuZCBkYXkgMSBjZWxscwp0c25lX291dCA8LSBSdHNuZShkaXN0KGdyb3VwX29uZV9kYXRhKSkgIyBSdW4gVFNORQojIFNob3cgdGhlIG9iamVjdHMgaW4gdGhlIDJEIHRzbmUgcmVwcmVzZW50YXRpb24KdHNuZURheTAxIDwtIHFwbG90KHg9dHNuZV9vdXQkWVssMV0sIHk9dHNuZV9vdXQkWVssMl0sY29sb3I9ZGF0YV9kYXlbaW5kZXhEYXkwMV0pICsKICBsYWJzKGNvbG91ciA9ICJDZWxsIFR5cGUiLCB4ID0gInRzbmUxIiwgeSA9ICJ0c25lMiIpICsKICBnZ3RpdGxlKCJ0LVNORSBvbmx5IGRheSAwIGFuZCAxIikgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xNCkscGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpIAoKdHNuZURheTAxCgojd2lsbCBub3QgYmUgbmVlZGVkOiBkb24ndCBrZWVwIGJpZyBkYXRhCnJlbW92ZSh0c25lX291dCkKI3JlbW92ZSh0c25lRGF5MDEpCmBgYAoKVGhlIHQtU05FIGNhbiBjbGVhcmx5IG5vdCBzZXBhcmF0ZSB0aGUgMiBzYW1wbGVzIGZyb20gZWFjaCBvdGhlci4gRmluYWxseSBsZXQncyBpbnZlc3RpZ2F0ZSB3aGV0aGVyIHRoZXkgY2FuIGJlIHNlcGFyYXRlZCB3aXRoIGEgdC1TTkUgaW4gMyBkaW1lbnNpb246CgpgYGB7ciB0c25lX2RheTAxXzNEfQp0c25lX291dCA8LSBSdHNuZShkaXN0KGdyb3VwX29uZV9kYXRhKSwgZGltcyA9IDMpICMgUnVuIFRTTkUgaW4gMyBkaW1lbnNpb25zCgpwbG90X2x5KHg9dHNuZV9vdXQkWVssMV0sCiAgICAgICAgeT10c25lX291dCRZWywyXSwKICAgICAgICB6PXRzbmVfb3V0JFlbLDNdLAogICAgICAgIHR5cGU9InNjYXR0ZXIzZCIsCiAgICAgICAgY29sb3I9ZGF0YV9kYXlbaW5kZXhEYXkwMV0sCiAgICAgICAgbW9kZT0ibWFya2VycyIpICU+JSAKICBsYXlvdXQodGl0bGUgPSAndC1TTkUgZGF5IDAgYW5kIDEgM0QnKQoKI3dpbGwgbm90IGJlIG5lZWRlZDogZG9uJ3Qga2VlcCBiaWcgZGF0YQpyZW1vdmUodHNuZV9vdXQpCnJlbW92ZShncm91cF9vbmVfZGF0YSkKI3JlbW92ZSh0c25lRGF5MDEpCmBgYAoKV2UgY2FuIHN0aWxsIG5vdCBkaXN0aW5ndWlzaCBib3RoIHR5cGUgb2YgY2VsbHMuIFRoaXMgcmVhbGx5IHNob3dzIGhvdyBzaW1pbGFyIHRoZXkgYXJlLgoKIyMjIHQtU05FIG9mIERheSAwIGFuZCBEYXkgMQoKTm93IGxldCdzIGxvb2sgYXQgdGhlIGNsdXN0ZXIgRGF5IDMgYW5kIDcsIHRvIHNlZSBpZiB0aGV5IGNhbiBiZSBkaXN0aW5ndWlzaGVkLgoKYGBge3IgdHNuZV9kYXkzN30KI3RzbmUgb24gRGF5IDAvRGF5IDEgY2VsbHMgb25seQppbmRleERheTM3IDwtIHdoaWNoKGRhdGFfZGF5ICVpbiUgYygiRGF5IDMiLCJEYXkgNyIpKQpncm91cF90d29fZGF0YSA8LSBhbGl2ZV90c25lX2RhdGFbaW5kZXhEYXkzNywgXSAjc2VsZWN0aW5nIG9ubHkgZGF5IDAgYW5kIGRheSAxIGNlbGxzCnRzbmVfb3V0IDwtIFJ0c25lKGRpc3QoZ3JvdXBfdHdvX2RhdGEpKSAjIFJ1biBUU05FCiMgU2hvdyB0aGUgb2JqZWN0cyBpbiB0aGUgMkQgdHNuZSByZXByZXNlbnRhdGlvbgp0c25lRGF5MzcgPC0gcXBsb3QoeD10c25lX291dCRZWywxXSwgeT10c25lX291dCRZWywyXSxjb2xvcj1kYXRhX2RheVtpbmRleERheTM3XSkgKwogIGxhYnMoY29sb3VyID0gIkNlbGwgVHlwZSIsIHggPSAidHNuZTEiLCB5ID0gInRzbmUyIikgKwogIGdndGl0bGUoInQtU05FIG9ubHkgZGF5IDMgYW5kIDciKSArCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTE0KSxwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgCgp0c25lRGF5MzcKCiN3aWxsIG5vdCBiZSBuZWVkZWQ6IGRvbid0IGtlZXAgYmlnIGRhdGEKcmVtb3ZlKHRzbmVfb3V0KQojcmVtb3ZlKHRzbmVEYXkzNykKYGBgCgpBcyBiZWZvcmUsIHRoZSAyIHR5cGUgb2YgY2VsbHMgY2Fubm90IGJlIGRpc3Rpbmd1aXNoZWQgd2l0aCBhIHQtU05FIHBsb3QgaW4gMkQuIFRoZXkgd2lsbCBwcm9iYWJseSBub3QgYmUgZGlzdGluZ3Vpc2hhYmxlIGluIDNEIGJ1dCBsZXQncyBiZSBzdXJlOgoKYGBge3IgdHNuZV9kYXkzN18zRH0KdHNuZV9vdXQgPC0gUnRzbmUoZGlzdChncm91cF90d29fZGF0YSksIGRpbXMgPSAzKSAjIFJ1biBUU05FIGluIDMgZGltZW5zaW9ucwoKcGxvdF9seSh4PXRzbmVfb3V0JFlbLDFdLAogICAgICAgIHk9dHNuZV9vdXQkWVssMl0sCiAgICAgICAgej10c25lX291dCRZWywzXSwKICAgICAgICB0eXBlPSJzY2F0dGVyM2QiLAogICAgICAgIGNvbG9yPWRhdGFfZGF5W2luZGV4RGF5MzddLAogICAgICAgIG1vZGU9Im1hcmtlcnMiKSAlPiUgCiAgbGF5b3V0KHRpdGxlID0gJ3QtU05FIGRheSAzIGFuZCA3IDNEJykKCiN3aWxsIG5vdCBiZSBuZWVkZWQ6IGRvbid0IGtlZXAgYmlnIGRhdGEKcmVtb3ZlKHRzbmVfb3V0KQpyZW1vdmUoZ3JvdXBfdHdvX2RhdGEpCmBgYAoKTm90IHN1cHJpc2luZ2x5LCB0aGUgc2Vjb25kIGNsdXN0ZXIgY2Fubm90IGJlIHNlcHJhdGVkIGZ1cnRoZXIgd2l0aCAzIGRpbWVuc2lvbmFsIHQtU05FLgoKCiMgRml0IGxpbmVhciBtb2RlbAoKTm90ZSB0aGF0IGZvciBmaXR0aW5nIGxpbmVhciBtb2RlbHMsIHdlIGNhbm5vdCB1c2UgdGhlIERBVEFTRVEgbGlicmFyeSBhcyBpdCByZXF1aXJlcyBjb3VudHMgKGkuZS4gZGlzY3JldGUgdmFsdWVzKS4gV2Ugbm93IGhhdmUgY29udGludW91cyB2YWx1ZXMgYmVjYXVzZSBvZiB0aGV5IHdheSB3ZSBub3JtYWxpemVkIHRoZSBkYXRhLgoKIyMgVm9vbQoKIyMjIE1lYW4tVmFyaWFuY2UgdHJlbmQKCkZpcnN0IGxldCB1cyB2aXN1YWxpemUgdGhlIG1lYW4tdmFyaWFuY2UgdHJlbmQsIHRvIHNlZS4gTm90ZTogaGVyZSBpdCBpcyBpbXBvcnRhbnQgdGhhdCB3ZSB1c2Ugb25seSB0aGUgZ2VuZXMgd2l0aCBubyBub24gemVybyB2YWx1ZXMgZm9yIGV2ZXJ5IHNhbXBsZSBhcyB3ZSBjYW4gc2VlIGluIHBhcmFncmFwaCAxNS4zIG9mIChsaW1tYSBtYW51YWwpW2h0dHBzOi8vd3d3LmJpb2NvbmR1Y3Rvci5vcmcvcGFja2FnZXMvZGV2ZWwvYmlvYy92aWduZXR0ZXMvbGltbWEvaW5zdC9kb2MvdXNlcnNndWlkZS5wZGZdLiBGcm9tIHRoZSBzYW1lIGFydGljbGUgdGhleSBzYXkgdGhhdCBhcyBhIHJ1bGUgb2YgdGh1bWIgd2Ugc2hvdWxkIGtlZXAgb25seSBnZW5lcyB0aGF0IGhhdmUgYSAgCgpgYGB7ciB2b29tX21lYW4tdmFyaWFuY2V9CiN3b3JraW5nIC4uLiBIT1cgVE8gVVNFIERBVEFERVNFUSBPTiBOT1JNQUxJWkVEID0+IE5PVCBDT1VOVFMgQU5ZIE1PUkU/PyArIElTIElUIFdPUlRIIElUID8gY0FOIHdlIHJvdW5kID8KI2RhdGFERVNlcSA8LSBybG9nKGFzLm1hdHJpeChkYXRhKSwgYmxpbmQ9RkFMU0UgKQoKI21ha2VzIGEgY29udmVuaWVudCBkZ2Ugb2JqZWN0IGZvciBhbmFseXNpcwojdCA8LSBuX2RhdGFbd2hpY2gocm93U3VtcyhuX2RhdGEpID4gMzAwKSxdIApkZ2UgPC0gREdFTGlzdChjb3VudHM9ZGF0YU5aLCBncm91cCA9IGRhdGFfZGF5KQojIGFwcGxpZXMgVE1NIG5vcm1hbGl6YXRpb24gdG8gZGdlCgojaXNFeHByIDwtIHJvd1N1bXMoZGdlJGNvdW50cykgPiAxMDAwCiNkZ2UgPC0gZGdlW2lzRXhwcixdCmRnZSA8LSBjYWxjTm9ybUZhY3RvcnMoZGdlKQpkYXRhX3Zvb21lZCA8LSB2b29tKGRnZSxkZXNpZ24scGxvdD1UUlVFKQoKI3dpbGwgbm90IGJlIG5lZWRlZDogZG9uJ3Qga2VlcCBiaWcgZGF0YQpyZW1vdmUoZGdlKQpgYGAKClRoZSBtZWFuLXZhcmlhbmNlIHRyZW5kIGlzIHN1cHJpc2luZzogaXQgZG9lc24ndCBsb29rIGZsYXQgZW5vdWdoLiBUaGUgZmlyc3QgaHlwb3J0aGVzaXMgd2UgaGFkIGlzIHRoYXQgd2UgdGhlcmUgd2FzIGEgcHJvYmxlbSBiZWNhdXNlIHdlIG5vcm1hbGl6ZSBieSBzYW1wbGVzIGFuZCB0aGVuIGxpbW1hIGRvZXMgaXQgYWdhaW4uIEJ1dCBub3Qgbm9ybWFpbGl6aW5nIG91ciBkYXRhIGRvZXNuJ3QgY2hhbmdlIHRoZSBjdXJ2ZSBvZiB0aGUgcGxvdC4gV2UgdGhlbiB0aG91Z2h0IHRoYXQgbWF5YmUgbGltbWEgd2FzIGRvaW5nIHNvbWV0aGluZyB0aGF0IHJlcXVpcmVkIGRpc2NyZXRlIGRhdGEgKGFzIGl0IGlzIG1hZGUgZm9yIGNvdW50IGRhdGEpLCBvdXIgZGF0YSBpc24ndCBkaXNjcmV0ZSBhcyB3ZSBub3JtYWlsaXplZCBpdCBiYXNlZCBvbiBzcGlrZSBSTkEuIEJ1dCByb3VuZGluZyB0aGUgZGF0YSBkb2Vzbid0IGNoYW5nZSBhbnl0aGluZyBlaXRoZXIuIFdlIHdpbGwgaGF2ZSB0byBsb29rIGRlZXBlciBhdCB0aGUgbWVhbmluZyBvZiB0ZSBjdXJ2ZSBvZiB0aGUgcGxvdCBhbmQgd2hldGhlciBvdXIgZGF0YSBkb2Vzbid0IGZvbGxvdyB0aGUgVm9vbSBhc3N1bXB0aW9ucy4gTm90ZSB0aGF0IHRoZSBkYXRhIG1heSBhbHNvIGJlIHN0cmFuZ2UgZHVlIHRvIHRoZSBuYXR1cmUgb2YgbWlSTkEgZGF0YSwgaW5kZWVkIGluIFJOQXNlcSB3ZSBvZnRlbiBoYXZlIGhpZ2ggdmFsdWUgb2YgY291bnRzIGJ1dCBpbiBtaVJOQSB0aGUgbnVtYmVyIG9mIGNvdW50cyBhcmUgbXVjaCBsb3dlci4gVGhpcyBjb3VsZCBjYXVzZSB0aGUgc3Bpa2Ugd2Ugc2VlIGJlbG93IHggPSB6ZXJvIChpLmUuIHZlcnkgbG93IG1lYW4pLgoKV2UgYWxzbyBzZWUgdGhhdCB0aGUgbWVhbiB2YXJpYW5jZSB0cmVuZCBzZWFtIHRvIGJlIGRlY3JlYXNpbmcgdmVyeSBxdWlja2x5IGFuZCBzdGVhZGlseSwgd2UgY2FuIHRodXMgY29uY2x1ZGUgdGhhdCB0aGUgZXhwZXJpbWVudCBzZWVtIHRvIGJlIG9mIGxvdyBiaW9sb2dpY2FsIHZhcmlhdGlvbi4gRm9yIG1vcmUgaW5mb3JtYXRpb24gcGxlYXNlIHNlZSB0aGUgIlJlbW92aW5nIGhldGVyb3NjZWRhc2NpdHkgZnJvbSBjb3VudCBkYXRhIiBzdWJwYXJ0IG9mICh0aGlzIHBhcGVyKVtodHRwczovL2YxMDAwcmVzZWFyY2guY29tL2FydGljbGVzLzUtMTQwOF0KCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiB0aGUgZGF0YSB3ZSBoYXZlOgoKYGBge3IgfQpkYXRhX3Zvb21lZFsxOjIsMToxMF0KYGBgCgojIyMjIE1lYW4gdmFyaWFuY2UgdHJlbmQgbm8gbG9nCgpOb3RlOiBTZWVpbmcgdGhlIHN0cmFuZ2UgcGxvdCBhYm92ZSBtYWtlcyB1cyB0aGluayB0aGF0IG1heWJlIG91ciBjb3VudCBkYXRhIGRvZXNuJ3QgbmVlZCB0byBiZSBsb2cgdHJhbnNmb3JtZWQuIExldCdzIGludmVzdGlnYXRlIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgbWVhbiBhbmQgdGhlIHZhcmlhbmNlIG9mIG91IGRhdGEuCgpgYGB7ciBzcXJ0NF9tZWFuLXZhcmlhbmNlfQojd29ya2luZyAuLi4gSE9XIFRPIFVTRSBEQVRBREVTRVEgT04gTk9STUFMSVpFRCA9PiBOT1QgQ09VTlRTIEFOWSBNT1JFPz8gKyBJUyBJVCBXT1JUSCBJVCA/IGNBTiB3ZSByb3VuZCA/CiNkYXRhREVTZXEgPC0gcmxvZyhhcy5tYXRyaXgoZGF0YSksIGJsaW5kPUZBTFNFICkKCiN0YWtlcyBvbmx5IGdlbmVzIHRoYXQgYXJlIG5vbiB6ZXJvIGluIG1hbnkgc2FtcGxlcwojdCA8LSBuX2RhdGFbd2hpY2gocm93U3VtcyhuX2RhdGEpID4gMzAwKSxdIAoKI3RyaWVzIHBsb3R0aW5nIGRpcmVjdGx5IHdpdGhvdXQgdm9vbQptIDwtIHJvd01lYW5zKGRhdGFOWikKUm93U2lnbWFTcXJ0IDwtIGZ1bmN0aW9uKHgpIHsKICAocm93U3VtcygoeCAtIHJvd01lYW5zKHgpKV4yKS8oZGltKHgpWzJdIC0gMSkpXigxLzQpCn0KdiA8LSBSb3dTaWdtYVNxcnQoZGF0YU5aKQoKcGxvdHh5IDwtIGRhdGEuZnJhbWUobWVhbj1tLHNpZ21hU3FydD12KQpnZ3Bsb3QocGxvdHh5LCBhZXMoeD1tZWFuLCB5PXNpZ21hU3FydCkpICsKICAgIGdlb21fcG9pbnQoc2hhcGU9MSkgKyAgICAjIFVzZSBob2xsb3cgY2lyY2xlcwogICAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCAgICMgQWRkIGxpbmVhciByZWdyZXNzaW9uIGxpbmUKICAgICAgICAgICAgICAgIHNlPUZBTFNFKSArICMgRG9uJ3QgYWRkIHNoYWRlZCBjb25maWRlbmNlIHJlZ2lvbgogIHlsaW0oMCwgNzUwMCkgKyAKICB4bGltKDAsNzUwMCkgKyAKICBnZ3RpdGxlKCJNZWFuIHZhcmlhbmNlIHJlbGF0aW9uc2hpcCBub3QgVm9vbSIpICsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTQpLHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSAKCmBgYAoKRnJvbSB0aGlzIHBsb3Qgd2UgY2xlYXJseSBzZWUgdGhhdCBvdXIgdmFyaWFuY2UgZ3Jvd3Mgd2l0aCBmb3VydGggcG9xZXIgb2Ygb3VyIG1lYW4uIFRoZSByZWFzb25pbmcgYmVoaW5kIHRoaXMgZGlmZmVyZW50IHJlbGF0aW9uc2hpcCBpcyBzdGlsbCB1bmNsZWFyIHRvIHVzICg/Pz8/Pz8/Pz8/Pz8/IGJpb2xvZ2ljYWxseSksIGJ1dCBpdCBjb3VsZCBpbmRpY2F0ZSB0aGF0IHdlIHNob3VsZG4ndCB3b3JrIHdpdGggdGhlIGRlZmF1bHQgbGltbWEgcGFja2FnZSBhbmQgdGhhdCB3ZSBzaG91bGQgbWF5YmUgZG8gdGhlIGFuYWx5c2lzIG1hbnVhbGx5ICg/Pz8/Pz8/PykuICAKCiMjIyBGaXQgbGluZWFyIG1vZGVsCgpgYGB7ciB0ZXN0X2xpbmVhcl9tb2RlbCB9CgpmaXQgPC0gbG1GaXQoZGF0YV92b29tZWQsIGRlc2lnbikKZml0IDwtIGNvbnRyYXN0cy5maXQoZml0LCBjb250cmFzdHM9Y29udHJhc3RNYXRyaXgpCmVmaXQgPC0gZUJheWVzKGZpdCkKdG9wVGFibGUoZWZpdCwgY29lZj1jb2xuYW1lcyhjb2VmKGVmaXQpKSkKcGxvdFNBKGVmaXQpCgojd2lsbCBub3QgYmUgbmVlZGVkOiBkb24ndCBrZWVwIGJpZyBkYXRhCnJlbW92ZShmaXQpCnJlbW92ZShkYXRhX3Zvb21lZCkKYGBgCgpIZXJlIHRoZXJlIGlzIGEgcHJvYmxlbSBhcyB3ZSBkbyBub3Qgc2VlIHRoZSBmaXR0ZWQgbGluZSAoPz8/Pz8pLgoKCiMjIyMgRXhhbWluaW5nIHRoZSBudW1iZXIgb2YgREUgZ2VuZXMKCkxldCdzIG5vdyBsb29rIGF0IGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGxldmVscyBvZiBnZW5lcy4gTm90ZSB0aGF0IHRoZSBhZGp1c3RlZCBwLXZhbHVlIGN1dG9mZiBpcyA1JS4KCmBgYHtyIHRlc3RfbGluZWFyX21vZGVsX3N1bW1hcnkgfQpkdCA8LSBkZWNpZGVUZXN0cyhlZml0KQpzdW1tYXJ5KGR0KQpgYGAKCkFzIHdlIGhhdmUgYWxyZWFkeSBwcmV2aW91c2x5IHNlZW4gaW4gdGhlIG11bHRpcGxlIHBsb3RzIG9mIHRoZSBwcmV2aW91cyBzZWN0aW9uOiBtb3N0IGRpZmZlcmVudGlhbCBleHByZXNzZWQgZ2VuZXMgYXJlIGJldHdlZW4gZGF5IDAvMSBhbmQgMy83LiBXZSBhbHNvIG5vdGUgdGhhdCBhIGxvdCBvZiBnZW5lcyBpbiBEYXkgMyBhbmQgNyBhcmUgZG93bnJlZ3VsYXRlZCAoY29tcGFyZWQgdG8gZGF5IDAgYW5kIDEpLgoKIyMjIyBGaW5kaW5nIGdlbmVzIHRoYXQgYXJlIG9mdGVuIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBjb21wYXJlZCB0byBkYXkgMAoKTGV0J3MgbG9vayBhdCB0aGUgZ2VuZXMgdGhhdCBhcmUgYWx3YXlzIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBjb21wYXJlZCB0byBkYXkgMCAKCmBgYHtyIGNvbW1vbl9ERV9nZW5lc19kYXkwIH0KIyBGaW5kaW5nIGdlbmVzIHRoYXQgYXJlIG5vdCB6ZXJvIGluIGV2ZXJ5IGNvbXBhcmFpc29uIHdpdGggZGF5IDAKY29tbW9uREVnZW5lc0RheTAgPC0gd2hpY2goZHRbLDFdIT0wICYgZHRbLDJdIT0wICYgZHRbLDNdIT0wKQpuYW1lcyhjb21tb25ERWdlbmVzRGF5MCkKYGBgCgpMZXQncyB2aXN1YWxpc2UgaXQgd2l0aCBhIG5pY2UgdmVubiBkaWFncmFtbQoKYGBge3IgZGF5MF9ERV92ZW5uIH0KdmVubkRpYWdyYW0oZHRbLDE6M10sIGNpcmNsZS5jb2w9YygidHVycXVvaXNlIiwgInNhbG1vbiIsICJncmVlbiIpKQpgYGAKCiMjIyMgRmluZGluZyBnZW5lcyB0aGF0IGFyZSBvZnRlbiBkaWZmZXJlbnRpYWxseSBiZXR3ZWVuIGRheSAwLzEgYW5kIGRheSAzLzcKCkxldCdzIGxvb2sgYXQgdGhlIGdlbmVzIHRoYXQgYXJlIGFsd2F5cyBkaWZmZXJlbnRpYWxseSBiZXR3ZWVuIGRheSAwLzEgYW5kIDMvNyBhcyB0aGV5IHNlZW0gdG8gYmUgdGhlIG9uZXMgb2YgaW50ZXJlc3QuCgpgYGB7ciBjb21tb25fREVfZ2VuZXNfZGF5MDEtMzcgfQojIEZpbmRpbmcgZ2VuZXMgdGhhdCBhcmUgbm90IHplcm8gaW4gZXZlcnkgY29tcGFyYWlzb24gd2l0aCBkYXkgMApjb21tb25ERWdlbmVzRGF5MDEzNyA8LSB3aGljaChkdFssMl0hPTAgJiBkdFssM10hPTAgJiBkdFssNF0hPTAgJiBkdFssNV0hPTApCm5hbWVzKGNvbW1vbkRFZ2VuZXNEYXkwMTM3KQpgYGAKCkxldCdzIHZpc3VhbGlzZSBpdCB3aXRoIGEgbmljZSB2ZW5uIGRpYWdyYW1tCgpgYGB7ciBkYXkwMTM3X0RFX3Zlbm4gfQp2ZW5uRGlhZ3JhbShkdFssMjo1XSwgY2lyY2xlLmNvbD1jKCJ0dXJxdW9pc2UiLCAic2FsbW9uIiwgImdyZWVuIiwieWVsbG93IikpCmBgYAo=